import { Paragraph, TextRun, ParagraphChild } from 'docx'

import { cssStylesToAttrs, getInlineStyles, tagsToAttrs } from './style'

export function richTextToParagraph(richText: string | string[]) {
  const paragraphNodes: Paragraph[] = []

  const richTextArr = Array.isArray(richText) ? richText : [richText]

  richTextArr.forEach((rich) => {
    paragraphNodes.push(
      new Paragraph({
        pageBreakBefore: true
      })
    )
    paragraphNodes.push(...convertRichTextToParagraphNodes(rich))
  })
  return paragraphNodes
}

/**
 * @see https://docx.js.org/
 */
function convertRichTextToParagraphNodes(richText: string) {
  const container = document.createElement('div')
  container.innerHTML = richText
  const parsedHtml = new DOMParser().parseFromString(richText, 'text/html')

  const paragraphNodes: Paragraph[] = []

  /**
   * 默认值需要在最后面判定，因为自定义合并判定子集样式优先
   * 自定义合并优先 target 值 其次是 source
   */
  const defaultNodeAttrs = cssStylesToAttrs({
    fontFamily: '方正仿宋_GBK',
    fontSize: '12pt'
  })

  parsedHtml.body.querySelectorAll('p,h1,h2,h3,h4,h6').forEach((element) => {
    const paragraphChildrenNodes: ParagraphChild[] = []

    const rootStyles = cssStylesToAttrs(getInlineStyles(element))

    recursionDeep(Array.from(element.childNodes))

    /**
     * TODO: 无法解析嵌套标签属性
     */
    function recursionDeep(childNodes: ChildNode[]) {
      childNodes.forEach((node) => {
        if (node.nodeType === Node.TEXT_NODE) {
          const deepAttrs = customMerge(
            customMerge(cssStylesToAttrs(getInlineStyles(node)), rootStyles),
            defaultNodeAttrs
          )

          paragraphChildrenNodes.push(
            new TextRun({
              text: node.textContent || '',
              ...deepAttrs
            })
          )
        } else if (node.nodeType === Node.ELEMENT_NODE) {
          const elementNode = node as any

          const attrsTag = ['strong', 'em', 'i']
          const tagNames = Array.from(
            elementNode.querySelectorAll('strong,em, i')
          ).map((node: any) => node.tagName.toLowerCase())
          const tagAttrs = tagsToAttrs(tagNames)

          const deepAttrs = customMerge(
            customMerge(
              customMerge(
                cssStylesToAttrs(getInlineStyles(elementNode)),
                rootStyles
              ),
              defaultNodeAttrs
            ),
            tagAttrs
          )

          if (!attrsTag.includes(elementNode.tagName.toLowerCase())) {
            paragraphChildrenNodes.push(
              new TextRun({
                text: elementNode.textContent,
                ...deepAttrs
              })
            )
          }
        }
      })
      const paragraph = new Paragraph({
        children: paragraphChildrenNodes,
        spacing: {
          line: rootStyles.lineSpacing,
          lineRule: 'exact'
        },
        alignment: rootStyles.alignment,
        indent: rootStyles.indent
      })
      paragraphNodes.push(paragraph)
    }
  })

  return paragraphNodes
}

// 自定义合并函数，忽略obj2中的undefined值
function customMerge(target, source) {
  Object.keys(source).forEach((key) => {
    if (Reflect.has(target, key) && target[key] !== undefined) return
    if (source[key] !== undefined) {
      target[key] = source[key]
    }
  })
  return target
}

export function recursiveHtmlNodes(
  childrenNodes: ChildNode[],
  paragraphNodes: Paragraph[] = []
) {
  childrenNodes.forEach((node) => {
    const paragraphNode = new Paragraph({
      children: [
        new TextRun({
          text: node.textContent || '',
          ...cssStylesToAttrs(getInlineStyles(node))
        })
      ]
    })

    paragraphNodes.push(paragraphNode)

    if (node.childNodes) {
      recursiveHtmlNodes(Array.from(node.childNodes), paragraphNodes)
    }
  })
  return paragraphNodes
}

// function isHeading(tagName: string) {
//   return 'h1,h2,h3,h4,h6'.includes(tagName)
// }

// export function getHeadingLevelByTagName(tagName: string) {
//   switch (tagName.toLocaleLowerCase()) {
//     case 'h1':
//       return HeadingLevel.HEADING_1
//     case 'h2':
//       return HeadingLevel.HEADING_2
//     case 'h3':
//       return HeadingLevel.HEADING_3
//     case 'h4':
//       return HeadingLevel.HEADING_4
//     case 'h5':
//       return HeadingLevel.HEADING_5
//     case 'h6':
//       return HeadingLevel.HEADING_6
//     default:
//       return undefined
//   }
// }
